package com.wcj.common.service.impl;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import com.wcj.common.dao.WcjDao;
import com.wcj.common.utils.BeanUtils;
import com.wcj.common.utils.ReflectionUtils;

public class WcjBaseService<T extends Serializable> {
	
	private WcjDao<T> wcjDao;
	
	public WcjBaseService(){
	}
	
	private boolean useObject(Object obj, Class target) {
		// 只对IValueObjectBaseService类型的对象进行判断
		if (obj instanceof WcjDao) {
			Class[] clazz = (obj.getClass()).getInterfaces();
			for (Class interClazz : clazz) {
				Type[] genType = interClazz.getGenericInterfaces();
				for (Type interGenType : genType)
					if (interGenType instanceof ParameterizedType
							&& ((ParameterizedType) interGenType)
									.getActualTypeArguments()[0] == target)
						return true;

			}
		}
		return false;
	}
	
	public WcjDao<T> getWcjDao() {
		
		if ( this.wcjDao != null ) {
			return this.wcjDao;// 如果dao已经被赋值,则返回
		}

		// 得到当前类的第一个泛型
		Class targetC = ReflectionUtils.getSuperClassGenricType(this.getClass());
		if (targetC == Object.class) {
			return this.wcjDao;
		}

		// 获得当前类的各个属性描述
		PropertyDescriptor[] thisDescriptors;
		try {
			thisDescriptors = Introspector.getBeanInfo(this.getClass())
					.getPropertyDescriptors();
		} catch (IntrospectionException e) {
			return this.wcjDao;
		}

		// 循环当前实例的每个成员变量,找到与c相等的成员变量,并对dao赋值
		for (PropertyDescriptor thisDescriptor : thisDescriptors) {
			String propertyName = thisDescriptor.getName();// 得到属性名称

			// 得到与这个属性名称对应的对象以及它对应的第一个泛型
			Object o = null;
			try {
				o = BeanUtils.getPrivateProperty(this, propertyName);
			} catch (Exception e) {
				continue;
			}// 如果属性不存在,则继续循环剩余的成员变量

			// 对dao进行赋值,得到o实现的接口与targetC进行比对,比对的过程详见方法useObject()
			if (useObject(o, targetC)) {
				wcjDao = (WcjDao<T>) o;
				break;// dao已经被赋值,则退出for循环
			}
		}
		
		return wcjDao;
	}

	public void setWcjDao(WcjDao<T> wcjDao) {
		this.wcjDao = wcjDao;
	}
	
}
